package com.guanghua.brick.db;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Time;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.sql.DataSource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.guanghua.brick.BrickConstant;
import com.guanghua.brick.util.StringUtil;

/**
 * 用于sql查询数据库的工具类.
 * 包含的方法都是查询数据库的方法，不包括修改的方法。
 * @author leeon
 *
 */
public class SQLUtil {
	
	private static final Log logger = LogFactory.getLog(SQLUtil.class);
	
	
	/**
	 * 创建数据库连接.
	 * 根据传入的connStr来选择.<br>
	 * 根据实现不同，connStr代表的意义不同，可以是jndi的字符串，spring的beanid，hibernate配置文件名称。
	 * <br><br>
	 * 
	 * 一般的项目架构中，这里打开的connection都是和事务已经绑定的connection，所以一般不用关闭。<br>
	 * 如果没有spring来做bean管理器，打开的connection可能是不和事务绑定的。<br>
	 *  
	 * @return 数据库链接。
	 * @throws Exception
	 */
	public static Connection openConnection(String connStr) throws Exception {
		ISQLConnection c = BrickConstant.getSQLConnection();
		return c.createConnection(connStr);
	}
	/**
	 * 创建数据库连接.
	 * 使用默认字符串创建数据库链接.可以参考openConnection()方法
	 * @return 数据库链接。
	 * @throws Exception
	 */
	public static Connection openConnection() throws Exception {
		return openConnection(null);
	}
	
	/**
	 * 获取数据源的方法.
	 * @return
	 * @throws Exception
	 */
	public static DataSource getDataSource() throws Exception {
		return null;
	}

	/**
	 * 获取数据源的方法.
	 * @param connStr
	 * @return
	 * @throws Exception
	 */
	public static DataSource getDataSource(String connStr) throws Exception {
		return null;
	}
	
	/**
	 * 利用sql查询数据库的方法，并返回页面控件可用数据库的方法.<br>
	 * <br>
	 * 方法会根据翻页器，排序器，过滤条件来组装sql，进行翻页查询。<br>
	 * 返回的结果是一个List列表，列表中的对象是Map，一个Map对应数据库返回的一行记录，<br>
	 * Map包含的格式是<String, String>，key对应的就是数据库字段的列名，value对应的就是数据库字段的列值。<br>
	 * 默认情况数据库的列名会被转换为java属性名的命名方式，比如user_name，会转化为userName。<br>
	 * 如果传入了countSql参数，那么方法会根据传入的countSql来计算总记录数。<br>
	 * <br><br>
	 * 
	 * 传入的SQL如果需要带入过滤条件，可以使用${}的表达式来进行配置，并配合过滤条件filter进行使用。<br>
	 * 比如界面的查询条件的input域的名字叫userName，<br>
	 * 那么在sql中可以写入一段过滤条件select * from user_table u where 1 = 1 ${and u.user_name like :userName}。<br>
	 * 如果用户在界面中填写了该input域，那么相应的filter对象中就会存在userName的key和对应值，<br>
	 * 这样${and u.user_name like :userName}就会被编译成and u.user_name like '%?%'的sql段拼接select * from user_table u where 1 = 1后。<br>
	 * userName在filter中对应的值将作为PreparedStatement的参数set给PreparedStatement。<br>
	 * 详细的${}用法可以参考brick reference文档。<br>
	 * <br><br>
	 * 
	 * 
	 * 翻页器，排序器，以及filter可以用相应的类中的newInstance方法来构造，构造的方法可以参考相应的类。
	 * @see PageInfo
	 * @see OrderInfo
	 * @see FilterInfo
	 * <br><br>
	 * 
	 * 
	 * @param conn 数据库连接，必须有，不能为null。
	 * @param sql 查询用的sql语句，必须有，不能为null。
	 * @param pager 翻页器，传入null，则不进行分页查询。
	 * @param order 排序器，传入null，则不进行排序查询。
	 * @param filter 过滤条件，传入null，不对sql的${}进行编译。
	 * @param countSql 特殊的计算记录数的sql语句，传入null，则使用默认的计算记录数的sql语句。
	 * @return 查询结果，这里的查询结果将全部转化为String类型，不在保持数据库中类型的特征。
	 * @throws SQLException
	 */
	public static List<Map<String, String>> query(Connection conn, String sql, PageInfo pager, OrderInfo order, Map<String, Object> filter, String countSql) throws SQLException {
		//调用query的核心方法
		ResultSet rs = queryCore(conn, sql, pager, order, filter, countSql);
		
		List<Map<String, String>> ret = resultToList(rs);
		rs.close();		
		return ret;
	}
	
	/**
	 * 利用sql查询数据库的方法，并返回页面控件可用数据库的方法.<br>
	 * <br>
	 * 方法会根据翻页器，排序器，过滤条件来组装sql，进行翻页查询。<br>
	 * 返回的结果是一个List列表，列表中的对象是Map，一个Map对应数据库返回的一行记录，<br>
	 * Map包含的格式是<String, String>，key对应的就是数据库字段的列名，value对应的就是数据库字段的列值。<br>
	 * 默认情况数据库的列名会被转换为java属性名的命名方式，比如user_name，会转化为userName。<br>
	 * 如果传入了countSql参数，那么方法会根据传入的countSql来计算总记录数。<br>
	 * <br><br>
	 * 
	 * 传入的SQL如果需要带入过滤条件，可以使用${}的表达式来进行配置，并配合过滤条件filter进行使用。<br>
	 * 比如界面的查询条件的input域的名字叫userName，<br>
	 * 那么在sql中可以写入一段过滤条件select * from user_table u where 1 = 1 ${and u.user_name like :userName}。<br>
	 * 如果用户在界面中填写了该input域，那么相应的filter对象中就会存在userName的key和对应值，<br>
	 * 这样${and u.user_name like :userName}就会被编译成and u.user_name like '%?%'的sql段拼接select * from user_table u where 1 = 1后。<br>
	 * userName在filter中对应的值将作为PreparedStatement的参数set给PreparedStatement。<br>
	 * 详细的${}用法可以参考brick reference文档。<br>
	 * <br><br>
	 * 
	 * 
	 * 翻页器，排序器，以及filter可以用相应的类中的newInstance方法来构造，构造的方法可以参考相应的类。
	 * @see PageInfo
	 * @see OrderInfo
	 * @see FilterInfo
	 * <br><br>
	 * 
	 * 
	 * @param conn 数据库连接，必须有，不能为null。
	 * @param sql 查询用的sql语句，必须有，不能为null。
	 * @param pager 翻页器，传入null，则不进行分页查询。
	 * @param order 排序器，传入null，则不进行排序查询。
	 * @param filter 过滤条件，传入null，不对sql的${}进行编译。
	 * @param countSql 特殊的计算记录数的sql语句，传入null，则使用默认的计算记录数的sql语句。
	 * @return 查询结果是Object，这里的查询结果将保留数据库字段类型的特征，如果数据库的字段是Date类型，这里拿到的也就是Java的Date类型。
	 * @throws SQLException
	 */
	public static List<Map<String, Object>> queryByObject(Connection conn, String sql, PageInfo pager, OrderInfo order, Map<String, Object> filter, String countSql) throws SQLException {
		//调用query的核心方法
		ResultSet rs = queryCore(conn, sql, pager, order, filter, countSql);
		
		List<Map<String, Object>> ret = resultToObjectList(rs);
		rs.close();		
		return ret;
	}
	
	/**
	 * 查询的核心方法
	 * @param conn 数据库连接，必须有，不能为null。
	 * @param sql 查询用的sql语句，必须有，不能为null。
	 * @param pager 翻页器，传入null，则不进行分页查询。
	 * @param order 排序器，传入null，则不进行排序查询。
	 * @param filter 过滤条件，传入null，不对sql的${}进行编译。
	 * @param countSql 特殊的计算记录数的sql语句，传入null，则使用默认的计算记录数的sql语句。
	 * @return 标准查询结果
	 * @throws SQLException
	 */
	private static ResultSet queryCore(Connection conn, String sql, PageInfo pager, OrderInfo order, Map<String, Object> filter, String countSql) throws SQLException {
		//编译sql
		SQLCompiler compiler = new SQLCompiler(sql, pager, order, filter);
		List<Object> param = compiler.getParam();
		List<Object> countParam = param;
		ResultSet rs = null;
		
		
		//现计算总记录数
		//利用框架拼装翻页SQL
		if (countSql == null) {
			countSql = compiler.getCountSql();
		//利用传入的countSql参数来计算总记录数
		} else {
			SQLCompiler countCompiler = new SQLCompiler(countSql, null, null, filter);
			countSql = countCompiler.getSql();
			countParam = countCompiler.getParam();
		}
		//查询总记录数,如果countsql是null，表示不需要查询
		if (countSql != null) {
			rs = queryByResultSet(conn, countSql, countParam);
			if (rs.next()) {
				String c = rs.getString(1);
				logger.debug("execute query count sql and result:" + c);
				int count = Integer.parseInt(c);
				pager.setRowCount(count);
			}
			rs.close();
		}
		
		//查询数据
		//然后翻页
		String pageSql = compiler.getPageSql();
		rs = queryByResultSet(conn, pageSql, param);
		
		return rs;
	}
	
	//以下是一些为了方便调用的重载的方法
	/**
	 * 利用sql查询数据库的方法，并返回页面控件可用数据库的方法.<br>
	 * 用法可以参考同名的query方法。
	 * 
	 * @param conn 数据库链接。
	 * @param sql 需要执行的sql，这里的sql不能使用${}表达式进行过滤条件配置。
	 * @return 查询结果。
	 * @throws SQLException
	 */
	public static List<Map<String, String>> query(Connection conn, String sql) throws SQLException {
		return query(conn, sql, null, null, null, null);
	}
	
	/**
	 * 利用sql查询数据库的方法，并返回页面控件可用数据库的方法.<br>
	 * 用法可以参考同名的query方法。
	 *  
	 * @param conn 数据库链接。
	 * @param sql 需要执行的sql，这里的sql不能使用${}表达式进行过滤条件配置。
	 * @param pager 翻页器。
	 * @return 查询结果。
	 * @throws SQLException
	 */
	public static List<Map<String, String>> query(Connection conn, String sql, PageInfo pager) throws SQLException {
		return query(conn, sql, pager, null, null, null);
	}
	
	
	/**
	 * 利用sql查询数据库的方法，并返回页面控件可用数据库的方法.<br>
	 * 用法可以参考同名的query方法。
	 * 
	 * @param conn 数据库链接。
	 * @param sql 需要执行的sql。
	 * @param filter 过滤条件。
	 * @return 查询结果。
	 * @throws SQLException
	 */
	public static List<Map<String, String>> query(Connection conn, String sql, Map<String, Object> filter) throws SQLException {
		return query(conn, sql, null, null, filter, null);
	}
	
	
	/**
	 * 利用sql查询数据库的方法，并返回页面控件可用数据库的方法.<br>
	 * 用法可以参考同名的query方法。
	 * 
	 * @param conn 数据库链接。
	 * @param sql 需要执行的sql。
	 * @param pager 翻页器。
	 * @param filter 过滤条件。
	 * @return 查询结果。
	 * @throws SQLException
	 */
	public static List<Map<String, String>> query(Connection conn, String sql, PageInfo pager, Map<String, Object> filter) throws SQLException {
		return query(conn, sql, pager, null, filter, null);
	}

	/**
	 * 利用sql查询数据库的方法，并返回页面控件可用数据库的方法.<br>
	 * 用法可以参考同名的query方法。
	 * 
	 * @param conn 数据库链接。
	 * @param sql 需要执行的sql。
	 * @param pager 翻页器。
	 * @param order 排序器。
	 * @param filter 过滤条件。
	 * @return 查询结果。
	 * @throws SQLException
	 */
	public static List<Map<String, String>> query(Connection conn, String sql, PageInfo pager, OrderInfo order, Map<String, Object> filter) throws SQLException {
		return query(conn, sql, pager, order, filter, null);
	}

	/**
	 * 利用sql查询数据库的方法，并返回页面控件可用数据库的方法.<br>
	 * 用法可以参考同名的query方法。
	 * 
	 * @param conn 数据库链接。
	 * @param sql 需要执行的sql，这里的sql不能使用${}表达式进行过滤条件配置。
	 * @return 查询结果，返回的Map中放入的是和数据库类型对应的Java对象类型。
	 * @throws SQLException
	 */
	public static List<Map<String, Object>> queryByObject(Connection conn, String sql) throws SQLException {
		return queryByObject(conn, sql, null, null, null, null);
	}
	
	/**
	 * 利用sql查询数据库的方法，并返回页面控件可用数据库的方法.<br>
	 * 用法可以参考同名的query方法。
	 *  
	 * @param conn 数据库链接。
	 * @param sql 需要执行的sql，这里的sql不能使用${}表达式进行过滤条件配置。
	 * @param pager 翻页器。
	 * @return 查询结果，返回的Map中放入的是和数据库类型对应的Java对象类型。
	 * @throws SQLException
	 */
	public static List<Map<String, Object>> queryByObject(Connection conn, String sql, PageInfo pager) throws SQLException {
		return queryByObject(conn, sql, pager, null, null, null);
	}
	
	
	/**
	 * 利用sql查询数据库的方法，并返回页面控件可用数据库的方法.<br>
	 * 用法可以参考同名的query方法。
	 * 
	 * @param conn 数据库链接。
	 * @param sql 需要执行的sql。
	 * @param filter 过滤条件。
	 * @return 查询结果，返回的Map中放入的是和数据库类型对应的Java对象类型。
	 * @throws SQLException
	 */
	public static List<Map<String, Object>> queryByObject(Connection conn, String sql, Map<String, Object> filter) throws SQLException {
		return queryByObject(conn, sql, null, null, filter, null);
	}
	
	
	/**
	 * 利用sql查询数据库的方法，并返回页面控件可用数据库的方法.<br>
	 * 用法可以参考同名的query方法。
	 * 
	 * @param conn 数据库链接。
	 * @param sql 需要执行的sql。
	 * @param pager 翻页器。
	 * @param filter 过滤条件。
	 * @return 查询结果，返回的Map中放入的是和数据库类型对应的Java对象类型。
	 * @throws SQLException
	 */
	public static List<Map<String, Object>> queryByObject(Connection conn, String sql, PageInfo pager, Map<String, Object> filter) throws SQLException {
		return queryByObject(conn, sql, pager, null, filter, null);
	}

	/**
	 * 利用sql查询数据库的方法，并返回页面控件可用数据库的方法.<br>
	 * 用法可以参考同名的query方法。
	 * 
	 * @param conn 数据库链接。
	 * @param sql 需要执行的sql。
	 * @param pager 翻页器。
	 * @param order 排序器。
	 * @param filter 过滤条件。
	 * @return 查询结果，返回的Map中放入的是和数据库类型对应的Java对象类型。
	 * @throws SQLException
	 */
	public static List<Map<String, Object>> queryByObject(Connection conn, String sql, PageInfo pager, OrderInfo order, Map<String, Object> filter) throws SQLException {
		return queryByObject(conn, sql, pager, order, filter, null);
	}	
	
	
	/**
	 * 利用sql查询数据库的方法，并返回页面控件可用数据库的方法.<br>
	 * 这里的过滤条件是用对象封装，而非Map<String, Object>的封装方式，用法可以参考同名的query方法。
	 * 
	 * @param conn 数据库链接。
	 * @param sql 需要执行的sql。
	 * @param pager 翻页器。
	 * @param order 排序器。
	 * @param filter 过滤条件，对象封装形式。
	 * @param countSql 特殊的计算记录数的sql语句，传入null，则使用默认的计算记录数的sql语句。
	 * @return 查询结果。
	 * @throws SQLException
	 */
	public static List<Map<String, String>> query(Connection conn, String sql, PageInfo pager, OrderInfo order, Object filter, String countSql) throws SQLException {
		QueryFilterHelper qfh = new QueryFilterHelper(filter);
		return query(conn, sql, pager, order, qfh.toMap(), countSql);
	}
	
	
	/**
	 * 利用sql查询数据库的方法，并返回页面控件可用数据库的方法.<br>
	 * 这里的过滤条件是用对象封装，而非Map<String, Object>的封装方式，用法可以参考同名的query方法。
	 * 
	 * @param conn 数据库链接。
	 * @param sql 需要执行的sql。
	 * @param filter 过滤条件，对象封装形式。
	 * @return 查询结果。
	 * @throws SQLException
	 */
	public static List<Map<String, String>> query(Connection conn, String sql, Object filter) throws SQLException {
		QueryFilterHelper qfh = new QueryFilterHelper(filter);
		return query(conn, sql, null, null, qfh.toMap(), null);
	}
	
	
	/**
	 * 利用sql查询数据库的方法，并返回页面控件可用数据库的方法.<br>
	 * 这里的过滤条件是用对象封装，而非Map<String, Object>的封装方式，用法可以参考同名的query方法。
	 * 
	 * @param conn 数据库链接。
	 * @param sql 需要执行的sql。
	 * @param pager 翻页器。
	 * @param filter 过滤条件，对象封装形式。
	 * @return 查询结果。
	 * @throws SQLException
	 */
	public static List<Map<String, String>> query(Connection conn, String sql, PageInfo pager, Object filter) throws SQLException {
		QueryFilterHelper qfh = new QueryFilterHelper(filter);
		return query(conn, sql, pager, null, qfh.toMap(), null);
	}
	
	/**
	 * 返回ResultSet查询结果的方法，主要用于一些不是返回给页面使用的查询.<br>
	 * 利用ResultSet来操作结果集比较方便，所以也不会有翻页或者过滤条件等信息传入，也是其他query方法使用的基础方法。
	 * @param conn 数据库链接。
	 * @param sql 查询的sql语句。
	 * @return ResultSet结果集。
	 * @throws SQLException 
	 */
	public static ResultSet queryByResultSet(Connection conn, String sql) throws SQLException {
		return queryByResultSet(conn, sql, null);
	}
	
	/**
	 * 返回ResultSet查询结果的方法，主要用于一些不是返回给页面使用的查询.<br>
	 * 利用ResultSet来操作结果集比较方便，所以也不会有翻页或者过滤条件等信息传入，也是其他query方法使用的基础方法。
	 * <br><br>
	 * 这里的SQLParamHelper用来封装查询的sql，以及需要set的过滤参数，使用方法参考SQLParamHelper类
	 * @see SQLParamHelper
	 * 
	 * @param conn 数据库链接。
	 * @param sqlhelper 查询的sql语句对象封装。
	 * @return ResultSet结果集。
	 * @throws SQLException 
	 */
	public static ResultSet queryByResultSet(Connection conn, SQLParamHelper helper) throws SQLException {
		return queryByResultSet(conn, helper.getSql(), helper.getParams());
	}
	
	
	/**
	 * 查询方法，内部使用。
	 * @param conn
	 * @param sql
	 * @param param
	 * @return
	 * @throws SQLException
	 */
	private static ResultSet queryByResultSet(Connection conn, String sql, List<Object> param) throws SQLException {
		PreparedStatement ps = conn.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
		logger.debug("execute query sql:" + sql);
		
		//参数传递
		if (param != null) {
			Iterator<Object> i = param.iterator();
			int index = 1;
			while (i.hasNext()) {
				Object o = i.next();
				logger.debug("execute query sql param" + index + ":" + o);
				if (o instanceof String) {
					ps.setString(index++, (String)o);
				} else if (o instanceof Integer) {
					ps.setInt(index++, ((Integer)o).intValue());
				} else if (o instanceof Long) {
					ps.setLong(index++, ((Long)o).longValue());
				} else if (o instanceof Float) {
					ps.setFloat(index++, ((Float)o).floatValue());
				} else if (o instanceof Double) {
					ps.setDouble(index++, ((Double)o).doubleValue());
				} else if (o instanceof Date) {
					ps.setDate(index++, new java.sql.Date(((Date)o).getTime()));
				} else if (o instanceof Time) {
					ps.setTime(index++, (Time)o);
				} else if (o == null) {
					ps.setString(index++, "");
				} else {
					ps.setString(index++, o.toString());
				}
			}
		}
		
		//执行查询
		ResultSet rs = ps.executeQuery();
		
		return rs;
	}
	
	
	/**
	 * 查询方法，内部使用。
	 * @param conn
	 * @param sql
	 * @param param
	 * @return
	 * @throws SQLException
	 */
	private static String queryOneValue(Connection conn, String sql, List<Object> param) throws SQLException {
		ResultSet rs = queryByResultSet(conn, sql, param);
		
		String ret = null;
		if (rs.next())
			ret = rs.getString(1);			
		rs.close();
		
		return ret;
	}
	
	/**
	 * 查询数据集的第一个行第一列的值的方法.<br>
	 * 当明确知道想要查的结果只有一个值，比如求count，取seq，用来快速获取第一行第一个值。
	 * <br><br>
	 * 
	 * 这里的SQLParamHelper用来封装查询的sql，以及需要set的过滤参数，使用方法参考SQLParamHelper类
	 * @see SQLParamHelper
	 * 
	 * @param conn 数据库链接。
	 * @param sqlhelper 查询的sql语句对象封装。
	 * @return String类型的结果值。如果没有结果，返回null。
	 * @throws SQLException
	 */
	public static String queryOneValue(Connection conn, SQLParamHelper helper) throws SQLException {
		return queryOneValue(conn, helper.getSql(), helper.getParams());
	}
	
	
	/**
	 * 查询数据集的第一个行第一列的值的方法.<br>
	 * 当明确知道想要查的结果只有一个值，比如求count，取seq，用来快速获取第一行第一个值。
	 * 
	 * @param conn 数据库链接。
	 * @param sql 查询用的sql。
	 * @return String类型的结果值。如果没有结果，返回null。
	 * @throws SQLException
	 */
	public static String queryOneValue(Connection conn, String sql) throws SQLException {
		return queryOneValue(conn, sql, null);
	}
	
	/**
	 * 将ResultSet转换成为List<Map<String, String>>封装方式的方法.<br>
	 * 其中List中的一个Map代表一行数据，Map中的key String对应数据库列名，value String对应数据在改行该列的值。
	 * @param rs 需要转化的ResultSet。
	 * @param useJavaColumnName 是否在转化时，将数据库的列名的命名方式改为java的命名方式，比如将user_name 转化为 userName。
	 * @return 转化的结果，全部转化为String。
	 * @throws SQLException
	 */
	public static List<Map<String, String>> resultToList(ResultSet rs, boolean useJavaColumnName) throws SQLException {
		List<Map<String, String>> ret = new ArrayList<Map<String, String>>();
		//获取元数据
		ResultSetMetaData md = rs.getMetaData();
		//循环获取数据
		while (rs.next()) {
			//生成一行记录结果集
			Map<String, String> map = new HashMap<String, String>();
			for (int i = 1; i <= md.getColumnCount(); i ++ ) {
				String dbColumnName = md.getColumnName(i);
				//如果是oracle的翻页字段，那么就不用加入数据集
				if (dbColumnName.equalsIgnoreCase(ISQLPagerSection.ORACLE_PAGER_ROWNUM)) continue;
				//如果使用java命名,进行替换
				if (useJavaColumnName) {
					String javaColumnName = StringUtil.databaseNameToJavaName(dbColumnName);
					logger.trace("db column name:["+dbColumnName+"] to java column name:["+javaColumnName+"]");
					map.put(javaColumnName, rs.getString(i));
				} else {
					map.put(dbColumnName, rs.getString(i));
				}
			}
			ret.add(map);
		}
		return ret;
	}
	
	/**
	 * 将ResultSet转换成为List<Map<String, String>>封装方式的方法.<br>
	 * 默认将结果集的列名有数据库命名转化为java属性命名。
	 * @param rs 需要转化的ResultSet。
	 * @return 转化的结果，全部转化为String。
	 * @throws SQLException
	 */
	public static List<Map<String, String>> resultToList(ResultSet rs) throws SQLException {
		return resultToList(rs, true);
	}
	
	/**
	 * 将ResultSet转换成为List<Map<String, String>>封装方式的方法.<br>
	 * 其中List中的一个Map代表一行数据，Map中的key String对应数据库列名，value String对应数据在改行该列的值。
	 * @param rs 需要转化的ResultSet。
	 * @param useJavaColumnName 是否在转化时，将数据库的列名的命名方式改为java的命名方式，比如将user_name 转化为 userName。
	 * @return 转化的结果，保持object类型。
	 * @throws SQLException
	 */
	public static List<Map<String, Object>> resultToObjectList(ResultSet rs, boolean useJavaColumnName) throws SQLException {
		List<Map<String, Object>> ret = new ArrayList<Map<String, Object>>();
		//获取元数据
		ResultSetMetaData md = rs.getMetaData();
		//循环获取数据
		while (rs.next()) {
			//生成一行记录结果集
			Map<String, Object> map = new HashMap<String, Object>();
			for (int i = 1; i <= md.getColumnCount(); i ++ ) {
				String dbColumnName = md.getColumnName(i);
				//如果是oracle的翻页字段，那么就不用加入数据集
				if (dbColumnName.equalsIgnoreCase(ISQLPagerSection.ORACLE_PAGER_ROWNUM)) continue;
				if (useJavaColumnName) {
					String javaColumnName = StringUtil.databaseNameToJavaName(dbColumnName);
					logger.trace("db column name:["+dbColumnName+"] to java column name:["+javaColumnName+"]");
					map.put(javaColumnName, rs.getObject(i));
				} else {
					map.put(dbColumnName, rs.getObject(i));
				}
			}
			ret.add(map);
		}
		return ret;
	}
	
	/**
	 * 将ResultSet转换成为List<Map<String, String>>封装方式的方法.<br>
	 * 默认将结果集的列名有数据库命名转化为java属性命名。
	 * @param rs 需要转化的ResultSet。
	 * @return 转化的结果，保持object特性。
	 * @throws SQLException
	 */
	public static List<Map<String, Object>> resultToObjectList(ResultSet rs) throws SQLException {
		return resultToObjectList(rs, true);
	}
	
//	public static void main(String[] a) throws Exception {
//		Map<String, Object> queryFilter = new HashMap<String, Object>();
//		//queryFilter.put("name", "刘");
//		//queryFilter.put("grade", "2");
//		//queryFilter.put("sex", new Integer[]{1, 2});
//		//queryFilter.put("sex", "2");
//		//queryFilter.put("birthday", "1979-12-08");
//		//queryFilter.put("minAge", "10");
//		
//		StringBuffer sql = new StringBuffer();
//		sql.append("select * from student where 1 = 1 ")
//			.append("${and name like name} ")
//			.append("${and no like no} ")
//			.append("${and sex = sex} ")
//			.append("${and department in department} ")
//			.append("${and grade in grade} ")
//			.append("${and birthday deq birthday} ")
//			.append("${and age >= minAge} ")
//			.append("${and age <= maxAge} ");
//		
//		Connection conn = SQLUtil.openConnection();
//		List<Map<String, String>> list = query(conn, sql.toString(), queryFilter);
//		
//		QueryResultHelper qrh = new QueryResultHelper(list);
//		qrh.setAlias("id, name, no, sex, age, birthday, department, grade");
//		
//		qrh.addListener(new QueryResultRowListener() {
//
//			public String modifyKey() {return "newColumn";}
//
//			public Object modifyValue(Map<String, String> row) {
//				return "1".equals(row.get("sex"))?"男":"女";
//			}
//			
//		});
//		List<Map<String, Object>> list1 = qrh.calculateQueryResult();
//		System.out.println(list1);
//		
//		conn.close();
//	}
}
